跳到主要内容

K3s 学习

K3s 是什么

K3s 是由 Rancher Labs 发布的一款开源、极轻量的 Kubernetes 发行版,通过了CNCF一致性认证,适用于在资源有限的环境中运行 Kubernetes。

单节点的 K3S 架构

20230505100848

1)k3s server 节点是运行 k3s server 命令的机器(裸机或者虚拟机),而 k3s Agent 节点是运行 k3s agent 命令的机器。

2)单点架构只有一个控制节点(在 K3s 里叫做 server node,相当于 K8s 的 master node),而且 K3s 的数据存储使用 sqlite 并内置在了控制节点上

3)在上图的这种配置中,每个 agent 节点都注册到同一个 server 节点。K3s 用户可以通过调用 server 节点上的 K3s API 来操作 Kubernetes 资源。

高可用的 K3S 架构

虽然单节点 k3s 集群可以满足各种用例,但对于 Kubernetes control-plane 的正常运行至关重要的环境,可以在高可用配置中运行 K3s。一个高可用 K3s 集群由以下几个部分组成:

20230505101132

1)K3s Server 节点:两个或者更多的 server 节点将为 Kubernetes API 提供服务并运行其他 control-plane 服务

2)外部数据库:外部数据存储(与单节点 k3s 设置中使用的嵌入式 SQLite 数据存储相反)

安装服务

# 后面的参数是为了让 kubectl 有权限访问
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn sh -

安装后可以检查一下版本号

20230505092259

# 这里其实也和 miniKube 一样,都是映射到别的命令来实现的
kubectl get pods -A

只不过 k3s 是通过 在 /usr/local/bin 中添加一个 kubectl 软链接到 k3s 的

20230505094713

可以通过 kubectl 查看 kube-system 运行的 pod 列表如下:

kubectl  get pod -n kube-system

20230505100634

可以发现并没有运行 apiserver、controller-manager、scheduler、kube-proxy 以及 flannel 等组件,因为这些都内嵌到了 k3s 进程。另外 k3s 已经给我们默认部署运行了 traefik ingress(反向代理插件)、metrics-server 等,不需要再额外安装了。

错误处理

如果使用的时候报错

20230505092749

# 使用 root 用户执行这个命令
echo "K3S_KUBECONFIG_MODE=\"644\"" >> /etc/systemd/system/k3s.service.env

# 或者直接改权限
sudo chmod 644 /etc/rancher/k3s/k3s.yaml

如果发现下面这种连不上服务的情况,可能是服务没有启动,需要先启动服务

$ sudo systemctl restart k3s  
$ systemctl status k3s.service

20230505160436

检查 k3s 的错误日志: K3s 日志的位置将根据你运行 K3s 的方式和节点的操作系统而有所不同。

  • 从命令行运行时,日志将发送到 stdout 和 stderr。
  • 使用 openrc 运行时,将在 /var/log/k3s.log 中创建日志。
  • 使用 systemd 运行时,日志将发送到 Journald 并可以使用 sudo journalctl -f -n 100 -u k3s 查看​​。
  • Pod 日志在 /var/log/pods 中。
  • Containerd 日志在 /var/lib/rancher/k3s/agent/containerd/containerd.log 中。
# 如果是端口占用则可以通过下面的命令查看
sudo netstat -tlnp | grep 10250

Kubernetes 仪表板

# https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml
# 注意粘贴到终端的时候要把,{ } 可能会被转义,导致命令执行失败
VERSION_KUBE_DASHBOARD=$(curl -w '%{url_effective}' -I -L -s -S https://github.com/kubernetes/dashboard/releases/latest -o /dev/null | sed -e 's|.*/||') && sudo k3s kubectl create -f https://raw.githubusercontent.com/kubernetes/dashboard/${VERSION_KUBE_DASHBOARD}/aio/deploy/recommended.yaml

20230505102149

sudo kubectl get pod -n kubernetes-dashboard

20230505103524

配置仪表盘的访问权限

# dashboard.admin-user.yml
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
# dashboard.admin-user-role.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard

部署 admin-user 配置:

sudo kubectl create -f dashboard.admin-user.yml -f dashboard.admin-user-role.yml

创建完成后获取 secret 中 token 的值。

sudo kubectl -n kubernetes-dashboard create token admin-user 

20230505105500

要访问仪表板,必须为 K3s 集群创建一个安全通道:

# 默认是 8001
sudo kubectl proxy
# 如果想要指定端口
sudo kubectl proxy --port=8009

现在,可以通过以下网址访问仪表盘:

http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/

使用 admin-user 持有者令牌进行登录(把上面的 Token 粘贴进来)。

20230505105741

安装其它的 Agent 节点

单节点 Server 安装是一个功能齐全的 Kubernetes 集群,它包括了托管工作负载 pod 所需的所有数据存储、control plane、kubelet 和容器运行时组件。除非你希望向集群添加容量或冗余,否则没有必要添加额外的 Server 或 Agent 节点。

TODO: 用到再添加负载

K3s on WSL 2

我们不能直接使用 K3s 官网上推荐的用 curl 命令安装 K3s,因为 WSL2 没有 supervisor. 因此我们采用如下方式安装 K3s:

设置私有的 Docker 仓库

K3s 为了降低资源消耗,将默认的 runtime 修改为 containerd,同时也内置了 Kubernetes CLI 工具 crictlctr

K3s 默认的 containerd 配置文件目录为 /var/lib/rancher/k3s/agent/etc/containerd/config.toml,但直接操作 containerd 的配置文件去设置镜像仓库或加速器相比于操作 docker 要复杂许多。

K3s 为了简化配置 containerd 镜像仓库的复杂度,K3s 会在启动时检 /etc/rancher/k3s/ 中是否存在 registries.yaml 文件,如果存在该文件,就会根据 registries.yaml 的内容转换为 containerd 的配置并存储到 /var/lib/rancher/k3s/agent/etc/containerd/config.toml,从而降低了配置 containerd 镜像仓库的复杂度。

提示

如果想使用一个私有的镜像仓库,那么需要在每个使用镜像仓库的节点上以 root 身份创建这个文件。如果是 agent 节点可能没有 /etc/rancher/k3s/registries.yaml 这个文件,需要手动创建,然后改动方法和 server 节点一样

修改文件

sudo vim /etc/rancher/k3s/registries.yaml

K3s 镜像仓库配置文件由两大部分组成:mirrors 和 configs:

  • Mirrors 是一个用于定义专用镜像仓库的名称和 endpoint 的指令
  • Configs 部分定义了每个 mirror 的 TLS 和证书配置。对于每个 mirror,你可以定义auth和/或tls

containerd 使用了类似 K8S 中 svc 与 endpoint 的概念,svc 可以理解为访问名称,这个名称会解析到对应的 endpoint 上。

也可以理解 mirror 配置就是一个反向代理,它把客户端的请求代理到 endpoint 配置的后端镜像仓库。mirror 名称可以随意填写,但是必须符合IP或域名的定义规则。并且可以配置多个 endpoint,默认解析到第一个 endpoint,如果第一个 endpoint 没有返回数据,则自动切换到第二个 endpoint,以此类推。

比如以下配置示例:

mirrors:
"localhost:5000":
endpoint:
- "http://127.0.0.1:5000"
"alsritter.icu:5000":
endpoint:
- "http://127.0.0.1:5000"
"docker.io":
endpoint:
- "https://xxxxxxx.mirror.aliyuncs.com"
- "https://registry-1.docker.io"

可以通过 crictl pull 10.11.42.30:5000/library/alpinecrictl pull alsritter.icu:5000/library/alpine 获取到镜像,但镜像都是从同一个仓库获取到的。

配置非安全(http)私有仓库,只需要在 endpoint 中指定 http 协议头的地址即可。 在没有 TLS 通信的情况下,需要为 endpoints 指定 http://,否则将默认为 https。

可以看到 Containerd 配置文件末尾追加了如下配置:

sudo cat /var/lib/rancher/k3s/agent/etc/containerd/config.toml

20230505165004

如果你已经启动了 k3s,可以通过以下命令重启 k3s 并设置 Docker Registry 镜像仓库:

sudo systemctl restart k3s

检查是否可以访问到私有仓库

# 从私有仓库拉取镜像
sudo crictl pull localhost:5000/jokes:latest

IP 地址变更导致的错误

先安装 etcdctl

ETCD_VERSION="v3.5.5"
ETCD_URL="https://github.com/etcd-io/etcd/releases/download/${ETCD_VERSION}/etcd-${ETCD_VERSION}-linux-amd64.tar.gz"
curl -sL ${ETCD_URL} | sudo tar -zxv --strip-components=1 -C /usr/local/bin
$ sudo ETCDCTL_ENDPOINTS='https://127.0.0.1:2379' \
ETCDCTL_CACERT='/var/lib/rancher/k3s/server/tls/etcd/server-ca.crt' \
ETCDCTL_CERT='/var/lib/rancher/k3s/server/tls/etcd/server-client.crt'\
ETCDCTL_KEY='/var/lib/rancher/k3s/server/tls/etcd/server-client.key' \
ETCDCTL_API=3 etcdctl member list

然后修改这个配置

$ sudo ETCDCTL_ENDPOINTS='https://127.0.0.1:2379' \
ETCDCTL_CACERT='/var/lib/rancher/k3s/server/tls/etcd/server-ca.crt' \
ETCDCTL_CERT='/var/lib/rancher/k3s/server/tls/etcd/server-client.crt' \
ETCDCTL_KEY='/var/lib/rancher/k3s/server/tls/etcd/server-client.key' \
ETCDCTL_API=3 etcdctl member update b273bc7741bcb020 \
--peer-urls="https://192.168.2.55:2379"

检查服务日志

可以通过以下方式去检查为啥服务没有起来

1、使用 kubectl describe deployment 命令查看 Deployment 的详细信息,包括 Pod 的创建状态、事件和各个容器的状态:

kubectl describe deployment <deployment-name>

20230505150917

2、使用 kubectl get pods 命令查看 Pod 的状态,包括 Pod 是否已经创建和正在运行的容器:

kubectl get pods

如果 Pod 处于 Pending 状态,可能是因为调度器无法找到合适的节点来运行 Pod。可以使用 kubectl describe pod 命令查看 Pod 的详细信息,包括 Pod 调度的状态和调度器的事件:

kubectl describe pod <pod-name>

20230505151307

3、使用 kubectl logs 命令查看容器的日志,以查找容器启动失败的原因:

kubectl logs <pod-name> <container-name>

如果容器未能启动,可能是由于容器映像中缺少必要的文件或配置,或者容器启动时发生错误。在容器日志中查找错误消息和异常堆栈跟踪,可以帮助你确定容器启动失败的原因。

4、最后,可以查看 Kubernetes 控制面板的事件日志,以查找与 Deployment 相关的事件和错误:

kubectl get events

这些事件可能包括 Pod 调度失败、容器启动失败等等。通过查看事件日志,可以快速定位 Deployment 未启动的原因。

复制 config 文件

sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config

使用 kubectl 生成 .kube/config 文件

Kubernetes 的 .kube/config 文件包含了访问 Kubernetes 集群所需的所有信息,包括集群、用户、命名空间和身份验证信息。这个文件通常在你设置或修改集群配置时自动创建和更新,但有时你可能需要手动创建或编辑它。

1、设置集群: 你需要有一个 Kubernetes 集群,并且知道它的 API server 地址。

kubectl config set-cluster <cluster-name> --server=https://<api-server-url> --insecure-skip-tls-verify

k3s 默认会在 /etc/rancher/k3s/k3s.yaml 路径下生成一个 kubeconfig 文件。可以查看这个文件来找到 API server 的地址

或者直接用命令

kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}'

2、设置证书: 如果你的集群使用了 TLS,你需要将客户端证书、客户端密钥和 CA 证书添加到配置中。

kubectl config set-credentials <user-name> --client-certificate=/path/to/client-certificate.crt --client-key=/path/to/client-key.key
kubectl config set-context <context-name> --cluster=<cluster-name> --user=<user-name>

3、设置上下文: 上下文是集群、用户和命名空间的组合。

kubectl config set-context <context-name> --cluster=<cluster-name> --user=<user-name> --namespace=<namespace>

4、使用上下文: 选择一个上下文作为当前上下文。

kubectl config use-context <context-name>

以上命令会在 ~/.kube/config 文件中生成相应的配置。你可以通过编辑这个文件来进一步调整配置。

手动创建 .kube/config 文件

你也可以直接手动创建或编辑 ~/.kube/config 文件。以下是一个示例配置文件的内容:

apiVersion: v1
clusters:
- cluster:
certificate-authority: /path/to/ca.crt
server: https://<api-server-url>
name: <cluster-name>
contexts:
- context:
cluster: <cluster-name>
namespace: <namespace>
user: <user-name>
name: <context-name>
current-context: <context-name>
kind: Config
preferences: {}
users:
- name: <user-name>
user:
client-certificate: /path/to/client.crt
client-key: /path/to/client.key

这个文件包含了连接到 Kubernetes 集群所需的所有信息。你需要将 <cluster-name>, <api-server-url>, <user-name>, <namespace>, <context-name>, /path/to/ca.crt, /path/to/client.crt, 和 /path/to/client.key 替换为实际的值。

注意:如果你的 Kubernetes 集群使用了某些特殊的身份验证方法(如 GKE 的 gcloud 或 AWS 的 aws-cli),你可能需要通过它们特定的命令行工具来获取或更新你的 Kubernetes 配置文件。

Reference